﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.Web.Mvc;
using System.Xml;
using 检查页面开放.Models;

namespace 检查页面开放.Controllers
{
    public class CheckLangeController : Controller
    {
        public static string ExcludeCodeFlag = "";
        // GET: CheckLange
        public ActionResult Index()
        {
            string strDoc = PathConst.SlAddress;
            string netAddress = Server.MapPath(" / ");
            HandleChsHelper.netAddress = netAddress;

            Regex.Replace("fdsafd<!--共-->放得开了/*斜巷*/范德萨/*bb*/a/cc/e", @"(/)(\*).*(\*)(/)", "", RegexOptions.Multiline);

            string delNotesDoc = "";
            string fileType = "";
            ArrayList rtnErrorList = new ArrayList();
            string strRex = @"[\u4e00-\u9fa5]";//中文正则
                                               //元数据排除文件
            string[] metaDataEx = System.IO.File.ReadAllText(Path.Combine(netAddress, "App_Data/MetaDataEx.txt"), Encoding.Default).Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
            //读取配置下需要检测的所有文件
            ArrayList list = HandleChsHelper.GetAllFilesList(strDoc);
            StringBuilder sb = new StringBuilder();
            string temp = "";

            //搜索到的文件地址清单
            string addressTemp = HandleChsHelper.netAddress.Replace('\\', '/') + "/result-langfile" + Guid.NewGuid().ToString() + ".txt";
            string strRexZw = @"[\u4e00-\u9fa5]";//中文正则
                                                 //元数据中的中文问题
            List<string> metadata = new List<string>();
            using (fs = new FileStream(addressTemp, FileMode.Create))
            {
                sw = new StreamWriter(fs);
                //文件中排除的标识符（代码片段白名单）
                ExcludeCodeFlag = ConfigurationManager.AppSettings["ExcludeCodeFlag"]; ;

                //遍历所有文件
                foreach (string item in list)
                {
                    //处理元数据
                    if (item.EndsWith(".metadata.config", StringComparison.OrdinalIgnoreCase))
                    {
                        FileInfo info = new FileInfo(item);
                        string content = System.IO.File.ReadAllText(item, Encoding.ASCII);
                        XmlDocument xmlDoc = new XmlDocument();

                        xmlDoc.LoadXml(content);

                        if (xmlDoc.InnerXml.IndexOf("application=\"" + PathConst.SysCode + "\"", StringComparison.OrdinalIgnoreCase) == -1 || metaDataEx.Contains(info.Name))
                        {
                            continue;
                        }
                        var tag = "tmplLayout";
                        if (PathConst.SysCode == "P7333")
                        {
                            tag = "script";
                            if (info.DirectoryName.EndsWith("BusinessScript")) {
                                tag = "scriptContent";
                            }
                        }
                        
                        XmlNodeList tmpLayOut = xmlDoc.DocumentElement.GetElementsByTagName(tag);
                        foreach (XmlNode node in tmpLayOut)
                        {
                            //data-comment="法人"  
                            var text = Regex.Replace(node.InnerText, @"(.*<!--).*(-->)", "", RegexOptions.Multiline);
                            text = Regex.Replace(text, "(data-comment=\").*(\")", "", RegexOptions.Multiline);
                            if (Regex.IsMatch(text, strRexZw))
                            {
                                metadata.Add(item + node.InnerXml + "\r\n");
                            }
                        }
                        continue;
                    }
                    //获得移除注释后的代码文本
                    delNotesDoc = HandleChsHelper.GetNotes(item, ExcludeCodeFlag);
                    //文件类型
                    fileType = item.Substring(item.LastIndexOf("."));
                    //是否含有中文
                    if (Regex.IsMatch(delNotesDoc, strRex))
                    {
                        //如果移除注释后还有中文，继续校验
                        //Console.WriteLine(item);
                        //得到错误代码片段List
                        rtnErrorList = getErrorCode(item, fileType, delNotesDoc);
                        if (rtnErrorList.Count > 0)
                        {
                            //sb.Append(item + "<br>");
                            sw.WriteLine(item);

                            sb.Append(item + "\r\n");
                            foreach (var dtl in rtnErrorList)
                            {
                                //temp += "<textarea rows=10 style='width : 100%' value='" + dtl.ToString() + "\r\n" + "' />" ;
                                temp = dtl.ToString() + "\r\n";
                                sb.Append(temp);
                            }
                            //sb.Append("<br>");
                        }
                    }
                }
            }

            //输出所有不规范的多语言文件代码片段
            ViewBag.ResultHtml = sb.ToString();
            //txtResult.Text = sb.ToString(); 

            ViewBag.ResultHtml2 = string.Join("\r\n", metadata);
            return View();
        }

        private static FileStream fs;
        private static StreamWriter sw;
        /// <summary>
        /// 得到错误代码片段List，进一步校验【逐行读取】
        /// </summary>
        /// <param name="filePath">文件地址</param>
        /// <param name="fileType">文件类型</param>
        /// <param name="fileTextAfterRex">初步移除注释后的代码文本</param>
        /// <returns></returns>
        public ArrayList getErrorCode(string filePath, string fileType, string fileTextAfterRex)
        {
            ArrayList errorList = new ArrayList();

            //前面没有移除的注释，此处进一步将遗漏的注释跳出校验
            Regex multiLineComment = new Regex(@"(?<!/)/\*([^*/]|\*(?!/)|/(?<!\*))*((?=\*/))(\*/)", RegexOptions.Compiled | RegexOptions.Multiline);
            string line = "";
            string strRex = @"[\u4e00-\u9fa5]";//中文正则
            string multiLineCommentRex = @"(?<!/)/\*([^*/]|\*(?!/)|/(?<!\*))*((?=\*/))(\*/)";

            using (StringReader srr = new StringReader(fileTextAfterRex))
            {
                int lineIndex = 0;
                while ((line = srr.ReadLine()) != null)
                {
                    //Console.WriteLine("行{0}:{1}", ++lineIndex, linesr);
                    if (line != null && !line.Equals(""))
                    {
                        if (fileType == ".cs")
                        {
                            if (line.Contains("[DtoDescription(") || line.Contains("[ActionDescription(") || line.Contains("#region") || line.Contains("[AppServiceScope(")
                                        || line.Contains("[ExportApi(") || line.Contains("EnumOption(") || line.Contains("DataApiOption(")
                                        || line.Contains("SubscriberInfo(")
                                        || line.Contains("ApiParam(")
                                        || line.Contains("ApiReturn(")
                                        || line.Contains("ApiModelProperty(")
                                        || line.Contains("ApiModel(")
                                        || line.Contains("[Event(")
                                        || line.Contains("[EventParam(") || line.Contains("[ProjectFilterDescription(") || line.Contains("#endregion")

                                        )
                            {
                                continue;
                            }
                            //
                        }
                        else if (fileType == ".cshtml")
                        {
                            //正则有问题，后续调整
                            //<span class="gd">@CommonLangRes.Common000047@*@@Language2batch 所属项目*@ </span>
                            if (line.Contains("@*"))
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (Regex.IsMatch(line, multiLineCommentRex))
                            {
                                continue;//遗漏的正则          dialog.tipSuccess("{##[lang:ggpt_ProjectOverview_0027]##}"/*"移除成功"*/);
                            }
                        }

                        //过滤代码白名单的行代码片段
                        if (line.Contains(ExcludeCodeFlag))
                        {
                            continue;
                        }


                        if (Regex.IsMatch(line, strRex))
                        {
                            errorList.Add(line);
                        }
                    }
                }
            }


            return errorList;
        }
    }

    public class HandleChsHelper
    {
        private static FileStream fs;
        private static StreamWriter sw;
        private static ArrayList list;

        public static string netAddress;
        public HandleChsHelper()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
        }
        public static ArrayList GetAllFilesList(string strRootFileAddress)
        {

            int leval = 0;
            string path = strRootFileAddress;

            list = new ArrayList();
            //Console.WriteLine("请输入需要列出内容的文件夹的完整路径和文件名：");
            //path = Console.ReadLine();
            path.Replace('\\', '/');


            fs = new FileStream(netAddress + "/result.txt", FileMode.Create);
            sw = new StreamWriter(fs);

            //开始写入文件
            //sw.WriteLine("遍历结果如下：");
            //sw.WriteLine(path);

            listDirectory(path);

            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
            //Console.WriteLine("请按任意键继续……");
            //Console.ReadKey();

            return list;
        }

        //排除文件夹，使用分号;分隔
        private static string strExcludeFiles = ConfigurationManager.AppSettings["ExcludeFiles"];

        //网站发布文件夹,00根目录，例如：C:\公司\git\slxt2.0\src\00_根目录
        private static string strSiteFolder = PathConst.SlRootAddress;
        //排除文件夹,例如：C:\公司\git\slxt2.0\src\99 packages
        private static string[] arrExcludeFolder = ConfigurationManager.AppSettings["ExcludeFolder"].Split(';');
        //排除临时生成文件夹
        private static string[] arrExcludeTypeFolder = { "bin", "obj", "" };
        /// <summary>
        /// 列出path路径对应的文件夹中的子文件夹和文件
        /// 然后再递归列出子文件夹内的文件和文件夹
        /// </summary>
        /// <param name="path">需要列出内容的文件夹的路径</param>
        /// <param name="leval">当前递归层级，用于控制输出前导空格的数量</param>
        private static void listDirectory(string path)
        {
            DirectoryInfo theFolder = new DirectoryInfo(@path);
            string[] arrExcludeFiles = strExcludeFiles.Split(';');

            //遍历文件
            foreach (FileInfo NextFile in theFolder.GetFiles())
            {
                if (NextFile.Extension.Contains(".css")) continue;
                if (NextFile.Extension.Contains(".csproj")) continue;
                if (NextFile.Extension.Contains(".json")) continue;
                //如果是js只读取售楼系统的

                //if (NextFile.Extension.Contains(".js")&& NextFile.FullName.ex) continue;

                if (NextFile.Extension.Contains(".js") || NextFile.Extension.Contains(".aspx") || NextFile.Extension.Contains(".cs") ||
                    (NextFile.Name.EndsWith(".metadata.config", StringComparison.OrdinalIgnoreCase)))
                {
                    //过滤掉排除的文件
                    if (arrExcludeFiles.Contains(NextFile.FullName.Replace(@"\\", @"\")))
                    {
                        continue;
                    }
                    sw.WriteLine(NextFile.FullName);
                    list.Add(NextFile.FullName);
                }

            }
            //是否是根目录
            var isGml = theFolder.FullName.EndsWith(@"src\00_根目录");
            //遍历文件夹
            foreach (DirectoryInfo NextFolder in theFolder.GetDirectories())
            {
                if (Exists(arrExcludeFolder, NextFolder.FullName)) continue;
                if (arrExcludeTypeFolder.Contains(NextFolder.Name)) continue;
                if (NextFolder.FullName.Contains(".UnitTest")) continue;
                if (isGml && (NextFolder.FullName.EndsWith("_metadata") || (NextFolder.FullName.EndsWith("Slxt") && PathConst.SysCode == "0011")) == false)
                {
                    continue;
                }
                listDirectory(NextFolder.FullName);
            }
        }
        public static bool Exists(string[] n, string num)
        {
            var s = n.Where(item => item == num);
            if (s.Count() > 0) return true;
            else return false;
        }
        /// <summary>
        /// 获得移除注释后的代码文本
        /// </summary>
        /// <param name="fileAddress">文件地址</param>
        /// <returns></returns>
        public static string GetNotes(string fileAddress, string ExcludeCodeFlag)
        {
            Regex singleLineComment = new Regex(@"//(.*)", RegexOptions.Compiled);
            Regex multiLineComment = new Regex(@"(?<!/)/\*([^*/]|\*(?!/)|/(?<!\*))*((?=\*/))(\*/)", RegexOptions.Compiled | RegexOptions.Multiline);
            Regex RegularString = new Regex("((?<!\\\\)\"([^\"\\\\]|(\\\\.))*\")", RegexOptions.Compiled | RegexOptions.Multiline);
            Regex AtString = new Regex("@(\"([^\"]*)\")(\"([^\"]*)\")*", RegexOptions.Multiline | RegexOptions.Compiled);

            Regex regAspx = new Regex(@"(?s)<!--.*?-->");
            Regex regAspx2 = new Regex(@"(?s)<%--.*?--%>");

            string text = new StreamReader(fileAddress).ReadToEnd();

            StringBuilder sb = new StringBuilder();
            string line;
            using (StringReader srr = new StringReader(text))
            {
                while ((line = srr.ReadLine()) != null)
                {
                    //Console.WriteLine("行{0}:{1}", ++lineIndex, linesr);
                    if (line != null && !line.Equals(""))
                    {
                        if (line.Trim().StartsWith("//") || line.Trim().StartsWith("[Description(") || line.Trim().StartsWith("#endregion") || line.Trim().StartsWith("[WfColumn("))
                        {
                            continue;
                        }
                        //过滤代码白名单的行代码片段
                        if (line.Contains(ExcludeCodeFlag))
                        {
                            //line =  line.Replace(line,"");
                            continue;
                        }
                        sb.Append(line + "\r\n");
                    }
                }
            }
            text = sb.ToString();

            Match mat = null;
            for (int i = 0; i < text.Length; i++)
            {
                if (text[i] == '\"')
                {
                    mat = RegularString.Match(text, i);
                    if (mat.Success)
                    {
                        i = mat.Index + mat.Length;
                    }
                }
                else if (text[i] == '@')
                {
                    mat = AtString.Match(text, i);
                    if (mat.Success)
                    {
                        i = mat.Index + mat.Length;
                    }
                }
                else if (text[i] == '/')
                {
                    mat = singleLineComment.Match(text, i);
                    if (mat.Success)
                    {
                        text = text.Remove(mat.Index, mat.Length);
                        i--;
                    }
                    else
                    {
                        mat = multiLineComment.Match(text, i);
                        if (mat.Success)
                        {
                            text = text.Remove(mat.Index, mat.Length);
                            i--;
                        }
                    }
                }
            }
            //Console.WriteLine(text);
            text = regAspx.Replace(text, "");
            text = regAspx2.Replace(text, "");
            //移除 /*fds */
            text = Regex.Replace(text, @"(/)(\*).*(\*)(/)", "", RegexOptions.Multiline);
            return text;
        }

    }
}